home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX302.ST / SECT.BAK < prev    next >
Encoding:
Text File  |  2001-02-09  |  17.7 KB  |  739 lines

  1. /* sect.c */
  2.  
  3. /* 
  4.  * Aug-23-88 jye. Change and add codes so that can be used for MS-DOS
  5.  * Dec-20-89 jye. Free a bug that HDX gives a error message when CD-ROM 
  6.  *                  is busy. 
  7.  */
  8.  
  9. #include "obdefs.h"
  10. #include "osbind.h"
  11. #include "mydefs.h"
  12. #include "part.h"
  13. #include "hdx.h"
  14. #include "addr.h"
  15. #include "error.h"
  16.  
  17. #define    ZBUFSIZ    0x4000        /* about 16k == 32 sectors */
  18. #define    ZCOUNT    (ZBUFSIZ/0x200)    /* ZCOUNT = 32 */
  19. #define MAXUNITS 16            /* max number of logical units */
  20.  
  21. #define PUNINFO struct _punifno
  22. PUNINFO {
  23.         WORD puns;    /* number of physical units */
  24.         BYTE pun[MAXUNITS];
  25.         LONG partition_start[MAXUNITS]; /* offset to partition on */
  26.                                         /* physical unit */
  27. };
  28. extern long ostack;        /* old stack pointer */
  29. extern UWORD errcode();        /* function to return error code */
  30. extern int yesscan;        /* the flag for the func. IBMGPART use */
  31. extern long sptrk;        /* the sector per track */
  32. extern int npart;        /* the number of partitions */
  33. extern int ext;            /* the index of extended partition */
  34. extern int extend;        /* the index of end extended partition */
  35. extern int showmany;    /* the flag for show the too many device alert box */
  36. extern char ttscsi;        /* the flag for SCSI if set */
  37. extern int t_scsi();    /* the assembly codes for check SCSI drive */
  38. extern int needscan;    /* TRUE: if it is the first time to scan the units */
  39.  
  40.  
  41. /*
  42.  * Logical-to-dev+partition mapping table.
  43.  */
  44. int nlogdevs;                /* # logical devices */
  45. LOGMAP logmap[EXTRALOGD];    /* logical dev map */
  46. int livedevs[MAXPHYSDEVS];    /* live devs flags; 1: device is alive */
  47. int typedev = 0x0000;        /* if set, driver is a removable driver */
  48. int typedrv = 0x0000;        /* if set, driver is a SCSI driver */
  49.  
  50.  
  51. /*
  52.  * Rebuild logical-to-physical mapping
  53.  * by reading and interpreting the root
  54.  * blocks for all physical devs.
  55.  *
  56.  */
  57.  
  58. rescan(flag, znm)
  59.  
  60. int flag;    /* 0: don't report medium change error; */
  61.             /* non-0: report medium change error; */
  62. int znm;    /* 1: do zero & markbad; 0: do partition & format */
  63.  
  64. {
  65.     int dev, scan=0;
  66.     char buf[512];
  67.     char sendata[16];
  68.     int partno, ret, inqret, i;
  69.     PART *partinfo;
  70.     char mask = 0x80;    /* 7th bit is set on */
  71.     int setmask;
  72.     int maxloop;
  73.  
  74.     ostack = Super(NULL);    /* set supervice mode */
  75.     t_scsi();                /* set the ttscsi flag if SCSI exists */
  76.     delay();
  77.     Super(ostack);
  78.     /* set the scent message box */
  79.     if ((needscan) && (ttscsi))
  80.         dsplymsg(scanmsg);
  81.  
  82.     /* disable all logical and physical devs */
  83.     for (dev = 0; dev < EXTRALOGD; ++dev)
  84.         logmap[dev].lm_physdev = -1;
  85.  
  86.     for (dev = 0; dev < MAXPHYSDEVS; ++dev)
  87.         livedevs[dev] = 0;
  88.  
  89.     /*
  90.      * Scan all physical devs
  91.      * and pick up partition structures.
  92.      */
  93.     nlogdevs = 0;
  94.     showmany = 0;
  95.     if (ttscsi)    {
  96.         maxloop = 16;
  97.         dev = 8;
  98.     } else {
  99.         maxloop = 8;
  100.         dev = 0;
  101.     }
  102. rerescan:
  103.     for (; dev < maxloop; ++dev)
  104.     {
  105.         /* initialize the buffer */
  106.         for (i = 0; i < 16; i++)        {
  107.             sendata[i] = 0;
  108.         }
  109.  
  110.         /* check see the drive is a what kind of drive */
  111.            ostack = Super(NULL);
  112.            delay();
  113.         inqret = inquiry(dev, (WORD)16, sendata);
  114.            delay();
  115.            Super(ostack);
  116.         setmask = 0x0001;
  117.         if (inqret & 0x08)    { /* the device is busy */
  118.             continue;
  119.         }
  120.         /* ret not equal OK, it may be a regular hard drive */
  121.         if (inqret == OK)         {     /* it is not a regular hard drive */
  122.             if (sendata[0])      {    /* it is not a hard drive */
  123.                 continue;
  124.             }
  125.               /* it is a SCSI drive */
  126.             /* set the relative bit, 1 is a SCSI, other is not */
  127.             typedrv |= setmask << dev;
  128.         }
  129.         if ((ret = getroot(dev, buf, (SECTOR)0)) < 0) {
  130.             if (znm)  rangelog(dev);
  131.             continue;
  132.         } else {        /* ret >= 0 */
  133.             if (ret > 0) {
  134.                 if (flag) {    /* if non-0, report error if medium changed */
  135.                     if (tsterr(ret) == OK)
  136.                         return ERROR;
  137.                 }
  138.                 if ((ret = getroot(dev, buf, (SECTOR)0))) {    /* try again */
  139.                     if (ret > 0 && flag && tsterr(ret) == OK)    {
  140.                         return ERROR;
  141.                     } else if ((ret > 0) && (!flag))    {
  142.                         if ((inqret == OK) && (sendata[1] & mask))    { 
  143.                             /* it is a removable drive */
  144.                             /* but forget insert the cartridge */
  145.                             err(instdrv);
  146.                             return ERROR;
  147.                         }
  148.                     }
  149.                     if (znm)    {
  150.                         rangelog(dev);
  151.                     }
  152.                     continue;
  153.                 }
  154.             }
  155.             if (inqret == OK)     {  /* it is a SCSI drive */
  156.                 if (sendata[1] & mask)    { /* it is a removable drive */
  157.                     /* set the relative bit, 1 is a removable, other is not */
  158.                     typedev |= setmask << dev;
  159.                 }
  160.             }
  161.             livedevs[dev] = 1;
  162.             yesscan = 1;
  163.             if (stgpart(dev, buf, (PART *)&partinfo) == ERROR)    {
  164.                 return ERROR;
  165.             }
  166.             if (ext != NO_EXT)    {
  167.                 sortpart(partinfo,SCAN_BS); 
  168.             }
  169.         for (partno = 0; partno < npart; ++partno) {
  170.             if ((partinfo[partno].p_flg & P_EXISTS) &&
  171.                 (partinfo[partno].p_siz != (SECTOR)0) &&
  172.                 (((partinfo[partno].p_id[0] == 'G') &&
  173.                  (partinfo[partno].p_id[1] == 'E') &&
  174.                  (partinfo[partno].p_id[2] == 'M'))   ||
  175.                  ((partinfo[partno].p_id[0] == 'B') &&
  176.                  (partinfo[partno].p_id[1] == 'G') &&
  177.                  (partinfo[partno].p_id[2] == 'M'))))   
  178.             {
  179.                 if (nlogdevs > EXTRALOGD)    {
  180.                     continue;
  181.                 }
  182.                 logmap[nlogdevs].lm_physdev = dev;
  183.                 logmap[nlogdevs].lm_partno = partno;
  184.                 logmap[nlogdevs].lm_start =  partinfo[partno].p_st;
  185.                 logmap[nlogdevs].lm_siz =      partinfo[partno].p_siz;
  186.                 ++nlogdevs;
  187.                 if (nlogdevs == MAXLOGDEVS)         {
  188.                     showmany = 1;
  189.                 }
  190.             }
  191.         }
  192.     }
  193.     inipart(partinfo, npart);
  194.     if (partinfo > 0)    Mfree(partinfo);
  195.     }
  196.     if ((ttscsi)&&(maxloop>8))    {
  197.         maxloop = 8;
  198.         dev = 0;
  199.         goto rerescan;
  200.     }
  201.     return OK;
  202. }
  203.  
  204. /* rerange the partition informations. */
  205.  
  206.  sortpart(pinfo, type)
  207.  PART *pinfo;
  208.  int type;                /* USER_ED = 1: for user interface use */
  209.                          /* SCAN_BS = 0: for rescan() and laybs() use */
  210.  {
  211.      int i, j, k;
  212.     PART rpart[2];
  213.  
  214.     if (ext == NO_EXT) return OK;    /* don't need sort */
  215.     for (i = 0; i < 2; i++)    { /* initialize the temple space */
  216.         rpart[i].p_flg = 0L;
  217.         rpart[i].p_st = 0L;
  218.         rpart[i].p_siz = 0L;
  219.         for (k = 0; k < 3; k++)
  220.             rpart[i].p_id[k] = '0';
  221.     }
  222.     /* save the partitions that after the extened partitions */
  223.     for (i = ext+1, j=0; i < 4; i++, j++)        {
  224.         if (pinfo[i].p_flg & P_EXISTS)    {
  225.             rpart[j].p_flg = P_EXISTS;
  226.             rpart[j].p_st = pinfo[i].p_st;
  227.             rpart[j].p_siz = pinfo[i].p_siz;
  228.             for (k = 0; k < 3; k++)
  229.                 rpart[j].p_id[k] = pinfo[i].p_id[k];
  230.         } 
  231.     }
  232.     /* move the extened partition to the front */
  233.      for (i=4, j = ext; i < npart; i++, j++)    {
  234.         if (pinfo[i].p_flg & P_EXISTS)    {
  235.             pinfo[j].p_flg = P_EXISTS;
  236.             pinfo[j].p_st = (type)?(pinfo[i].p_st):(pinfo[i].p_st + ROOTSECT);
  237.             pinfo[j].p_siz = (type)?(pinfo[i].p_siz):(pinfo[i].p_siz-ROOTSECT);
  238.             for (k = 0; k < 3; k++)
  239.                 pinfo[j].p_id[k] = pinfo[i].p_id[k];
  240.         } else { j--;}    /* stay with that space */
  241.     }
  242.     /* copy the not extended partitions back after the extended partitions */
  243.      for (i=0; i < 2; i++, j++)    {
  244.         if (rpart[i].p_flg & P_EXISTS)    {
  245.             pinfo[j].p_flg = P_EXISTS;
  246.             pinfo[j].p_st = rpart[i].p_st;
  247.             pinfo[j].p_siz = rpart[i].p_siz;
  248.             for (k = 0; k < 3; k++)
  249.                 pinfo[j].p_id[k] = rpart[i].p_id[k];
  250.         } else {j--;}
  251.     }
  252.     for (i = j; i < npart; i++)    { /* set the rest to 0 */
  253.         pinfo[i].p_flg = 0L;
  254.         pinfo[i].p_st = 0L;
  255.         pinfo[i].p_siz = 0L;
  256.         for (k = 0; k < 3; k++)
  257.             pinfo[i].p_id[k] = '0';
  258.     }
  259. }
  260.  
  261.  
  262. /* 
  263.  * check to find out the exist of device
  264.  */
  265.  
  266. rangelog(dev)
  267.  
  268. int dev;
  269.  
  270. {
  271.     PUNINFO *divinfo;
  272.     int devnum;
  273.  
  274.     ostack = Super(NULL);
  275.     divinfo = ((PUNINFO *) *((long *)(0x516)));
  276.     for (devnum = 0; devnum < MAXUNITS; ++devnum)    {
  277.         if ((int)(divinfo->pun[devnum] & 0x07) == dev)    {
  278.             delay();
  279.             nlogdevs++;
  280.         }
  281.     }
  282.     Super(ostack);
  283. }
  284.  
  285. /*
  286.  * From a PHYSICAL device unit (0->7)
  287.  * and a partition number (0->3), figure
  288.  * out the LOGICAL disk number ('C'->'P').
  289.  *
  290.  * return the LOGICAL disk number or
  291.  * ERROR if the PHYSICAL device doesn't exist.
  292.  *
  293.  */
  294. phys2log(pdev, pno)
  295. int  pdev;    /* physical device unit */
  296. int  pno;    /* partition number (0 -> 3) */
  297. {
  298.     int logdev;        /* index to step through partitions of a phys unit */
  299.  
  300.     for (logdev = 0; logdev < EXTRALOGD; logdev++) {
  301.         if (logmap[logdev].lm_physdev == pdev &&
  302.             logmap[logdev].lm_partno == pno)
  303.             return ('C'+logdev);
  304.     }
  305.     return ERROR;
  306. }
  307.  
  308.  
  309. /*
  310.  * Map block on logical device to
  311.  * block on physical device;
  312.  * return ERROR if the logical device
  313.  * doesn't exist.
  314.  */
  315. log2phys(adev, ablk)
  316. int *adev;
  317. SECTOR *ablk;
  318. {
  319.     int dev;
  320.     char xbuf[256];
  321.     
  322.     dev = *adev;
  323.     if (dev >= 0 && dev <= 15)
  324.     return OK;
  325.  
  326.     dev = toupper(dev);
  327.     if (dev >= 'C' && dev <= 
  328.                 ('C'+EXTRALOGD)) /* from C to 't' are 50 logic device */
  329.     {
  330.     dev -= 'C';
  331.     *adev = logmap[dev].lm_physdev;
  332.     *ablk = logmap[dev].lm_start + *ablk;
  333.     return OK;
  334.     }
  335.  
  336.     return ERROR;
  337. }
  338.  
  339.  
  340.  
  341. /*
  342.  * Return physical starting block# of a partition
  343.  *
  344.  */
  345. SECTOR 
  346. logstart(ldev)
  347. int ldev;    /* logical device */
  348. {
  349.     ldev = toupper(ldev);
  350.     if (ldev >= 'C' && ldev <= 
  351.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  352.         ldev -= 'C';
  353.         return (logmap[ldev].lm_start);
  354.     }
  355.     return ERROR;
  356. }
  357.  
  358.  
  359.  
  360. /*
  361.  * Return physical starting block# of a partition's data block.
  362.  *
  363.  */
  364. SECTOR 
  365. logend(ldev)
  366. int ldev;    /* logical device */
  367. {
  368.     ldev = toupper(ldev);
  369.     if (ldev >= 'C' && ldev <= 
  370.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  371.         ldev -= 'C';
  372.         return (logmap[ldev].lm_start+logmap[ldev].lm_siz-1);
  373.     }
  374.     return ERROR;
  375. }
  376.  
  377.  
  378. #define    MFM 17        /* sectors per track for MFM */
  379. #define    RLL 26        /* sectors per track for RLL */
  380.  
  381.  
  382. /*
  383.  * Check if dev's root block is intact.
  384.  * Return number of sectors per track on disk.
  385.  *
  386.  */
  387. chkroot(dev, bs)
  388. int dev;
  389. char *bs;
  390. {
  391.     extern long get3bytes();
  392.     SETMODE *mb;
  393.     int i, ret, set, scsidrv, mask=0x0001;
  394.     int cyl, head;
  395.     SECTOR size, msiz;    /* size of media */
  396.     char buf[512], sendata[32];
  397.     long dmaptr, tmpptr;
  398.     char *dmahigh=0xffff8609,
  399.          *dmamid=0xffff860b,
  400.          *dmalow=0xffff860d;
  401.     
  402.     size = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  403.     
  404.     ostack = Super(NULL);
  405.     
  406.     /* Get format parameters/ disk size from media */
  407.     set = typedev & (mask << dev);
  408.     scsidrv = typedrv & (mask << dev);
  409.     if ((set) || (scsidrv))    {
  410.         ret = mdsense(dev, 4, 0, 16, sendata);
  411.     } else    {
  412.         ret = mdsense(dev, 0, 0, 22, sendata);
  413.     }
  414.     delay();
  415.     Super(ostack);
  416.     
  417.     if (ret != 0) {
  418.         ret = errcode(dev);
  419.         if (tsterr(ret) != OK) 
  420.             return ERROR;
  421.         return (-3);    /* don't have to show the alert box */
  422.     }
  423.     
  424.     /* check what kind of sense data it returned  */
  425.     /* If full SCSI, will return number of blocks */
  426.     /* on disk at byte 5, 6 and 7.  If Adaptec,   */
  427.     /* will return 0 for number of blocks on disk */
  428.     /* on SCSI. */
  429.     
  430.     if (!(msiz = get3bytes(sendata+5))) {    /* no disk size returned? */
  431.         /* Yup, ie., it's adaptec's.  Interpret as SETMODE structure */
  432.         mb = (SETMODE *)sendata;
  433.     /* get number of cylinders */
  434.     cyl = mb->smd_cc[0];
  435.     cyl <<= 8;
  436.     cyl |= mb->smd_cc[1];
  437.     
  438.     /* get number of heads */
  439.     head = mb->smd_dhc;
  440.     
  441.     msiz = (SECTOR)head * (SECTOR)cyl * MFM;
  442.     
  443.     for (i = 0; i < 20; i++) {
  444.         if ((ret = rdsects(dev, 1, buf, msiz+i)) == OK) {
  445.         
  446.         /* find out whether data has been transferred, by
  447.               checking if dma pointer has been moved.      */
  448.  
  449.            ostack = Super(NULL);    /* get into Supervisor mode */
  450.            
  451.         dmaptr = *dmahigh;
  452.         dmaptr &= 0x0000003f;
  453.         dmaptr <<= 16;
  454.         tmpptr = *dmamid;
  455.         tmpptr &= 0x000000ff;
  456.         tmpptr <<= 8;
  457.         dmaptr |= tmpptr;
  458.         tmpptr = *dmalow;
  459.         tmpptr &= 0x000000ff;
  460.         dmaptr |= tmpptr;
  461.         
  462.             delay();
  463.             Super(ostack);        /* back to user mode */
  464.             
  465.         if (dmaptr != buf)
  466.             break;
  467.         } else {            /* rdsects return an error */
  468.         if (tsterr(ret) == OK) {
  469.                 break;
  470.         }
  471.             }
  472.         }
  473.     
  474.     if (ret == MDMCHGD)        /* check if error occurred */
  475.         return (ret);
  476.        
  477.     /* Determine if media is MFM or RLL */
  478.     if (i < 20)
  479.         msiz = (SECTOR)head * (SECTOR)cyl * RLL;
  480.     }
  481.         
  482.     if (size != msiz)
  483.         ret = ERROR;
  484.     else 
  485.         ret = OK;
  486.         
  487.     return (ret);
  488. }
  489.  
  490.  
  491. /*
  492.  * Chkparm()
  493.  *    Check if given logical device has the asssumed parameters.
  494.  * Assumptions are:
  495.  *    - 512 bytes/sector
  496.  *    - 2 sectors/cluster
  497.  *    - 1 reserved sector
  498.  *    - 2 FATs
  499.  *
  500.  * Input:
  501.  *    ldev - logical device number ('C' -> 'P').
  502.  *
  503.  * Return:
  504.  *    OK - parameters of partition match the assumptions
  505.  *    ERROR - something went wrong.
  506.  *
  507.  * Comment:
  508.  *    Number of FATs is assumed to be 2.  Cannot check this 
  509.  * because previous version of HDX did not put that in the boot
  510.  * sector.
  511.  */
  512. chkparm(ldev)
  513. int ldev;
  514. {
  515.     char bs[512];        /* boot sector */
  516.     BOOT *boot;            /* boot structure */
  517.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  518.     int ret;
  519.  
  520.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  521.         if (tsterr(ret) != OK)
  522.             err(bootread);
  523.         ret = ERROR;
  524.         goto parmend;
  525.     }    
  526.  
  527.     boot = (BOOT *)bs;
  528.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  529.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  530.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  531.     if (bps % BPS            /* bytes per sector == ratio of 512 ? */
  532.     || res != 1) {            /* num sectors reserved == 1 ? */
  533.     ret = ERROR;            /* Nope, different from assumptions */
  534.     goto parmend;
  535.     }
  536.     
  537.     /* Check if sectors per cluster make sense */
  538.     if (boot->b_spc != 2) {
  539.         ret = ERROR;
  540.         goto parmend;
  541.     }
  542.     
  543.     ret = OK;                /* If yes, return OK */
  544.  
  545. parmend:
  546.     return ret;
  547. }
  548.  
  549.  
  550. ichkparm(ldev)
  551. int ldev;
  552. {
  553.     char bs[512];        /* boot sector */
  554.     BOOT *boot;            /* boot structure */
  555.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  556.     int ret;
  557.  
  558.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  559.         if (tsterr(ret) != OK)
  560.             err(bootread);
  561.         ret = ERROR;
  562.         goto parmend;
  563.     }    
  564.  
  565.     boot = (BOOT *)bs;
  566.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  567.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  568.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  569.     if (bps != 512            /* bytes per sector == 512 ? */
  570.     || res != 1) {            /* num sectors reserved == 1 ? */
  571.     ret = ERROR;            /* Nope, different from assumptions */
  572.     goto parmend;
  573.     }
  574.     
  575.     /* Check if sectors per cluster make sense */
  576.     if ((siz >= 0x8000L && boot->b_spc != 4) ||
  577.         (siz < 0x8000L && boot->b_spc != 2)) {
  578.         ret = ERROR;
  579.         goto parmend;
  580.     }
  581.     
  582.     ret = OK;                /* If yes, return OK */
  583.  
  584. parmend:
  585.     return ret;
  586. }
  587.  
  588.  
  589. /*
  590.  * Get dev's root block.
  591.  *
  592.  */
  593. getroot(dev, buf, sect)
  594. int dev;
  595. char *buf;
  596. SECTOR sect;
  597. {
  598.     return rdsects(dev, 1, buf, sect);
  599. }
  600.  
  601.  
  602. /*
  603.  * Put dev's root block.
  604.  *
  605.  */
  606. putroot(dev, buf, sect)
  607. int dev;
  608. char *buf;
  609. SECTOR sect;
  610. {
  611.     return wrsects(dev, 1, buf, sect);
  612. }
  613.  
  614.  
  615. /*
  616.  *  Read sector(s) from dev.
  617.  *
  618.  *  Input:
  619.  *    dev - device number (logical or physical).
  620.  *    num - number of sectors to read.
  621.  *    buf - buffer to write data read.
  622.  *    sect - starting sector number to read from.
  623.  *
  624.  *  Return:
  625.  *    errnum - 0: if read is successful.
  626.  *         an error code: if read is unsuccessful.
  627.  */
  628. rdsects(dev, num, buf, sect)
  629. int dev;            /* device number (logical or physical) */
  630. UWORD num;            /* number of sectors to read */
  631. char *buf;
  632. SECTOR sect;            /* starting sector to read from */
  633. {
  634.     int errnum;
  635.  
  636.     if (log2phys(&dev, §) < 0)
  637.     return ERROR;
  638.  
  639.     ostack = Super(NULL);
  640.     errnum = hread(sect, num, buf, (UWORD)dev);
  641.     if (errnum == 04)    {     /* the drive is stop */
  642.         delay();
  643.         stunt(dev, 1);        /* start the drive */
  644.         delay();
  645.         errnum = hread(sect, num, buf, (UWORD)dev);
  646.     }
  647.     delay();
  648.     Super(ostack);
  649.  
  650.     if (errnum > 0) {
  651.         errnum = errcode(dev);
  652.     }
  653.         
  654.     return errnum;        /* return the error code */
  655. }
  656.  
  657.  
  658. /*
  659.  *  Write sector(s) to dev.
  660.  *
  661.  *  Input:
  662.  *    dev - device number (logical or physical).
  663.  *    num - number of sectors to write.
  664.  *    buf - buffer with data to be written.
  665.  *    sect - starting sector number to write to.
  666.  *
  667.  *  Return:
  668.  *    errnum - 0: if write is successful.
  669.  *         an error code: if write is unsuccessful.
  670.  */
  671. wrsects(dev, num, buf, sect)
  672. int dev;            /* device number (logical or physical */
  673. UWORD num;            /* number of sectors to write */
  674. char *buf;            /* buffer with data to be written */
  675. SECTOR sect;            /* starting sector to write to */
  676. {
  677.     int errnum;
  678.  
  679.     if (log2phys(&dev, §) < 0)
  680.     return ERROR;
  681.  
  682.     ostack = Super(NULL);
  683.     errnum = hwrite(sect, num, buf, (UWORD)dev);
  684.     if (errnum == 04)    {     /* the drive is stop */
  685.         delay();
  686.         stunt(dev, 1);        /* start the drive */
  687.         delay();
  688.         errnum = hwrite(sect, num, buf, (UWORD)dev);
  689.     }
  690.     delay();
  691.     Super(ostack);
  692.  
  693.     if (errnum > 0) {
  694.         errnum = errcode(dev);
  695.     }
  696.  
  697.     return errnum;
  698. }
  699.  
  700.  
  701. /*
  702.  * Zero range of sectors on dev.
  703.  *
  704.  */
  705. zerosect(dev, start, count)
  706. int dev;
  707. SECTOR start;
  708. UWORD count;
  709. {
  710.     char *zbuf;
  711.     int  v;
  712.     UWORD i;
  713.  
  714.     if ((zbuf = (char *)mymalloc(ZBUFSIZ)) <= 0)
  715.         return err(nomemory);
  716.         
  717.     if (log2phys(&dev, &start) < 0) {
  718.         free(zbuf);
  719.     return ERROR;
  720.     }
  721.  
  722.     fillbuf(zbuf, (long)ZBUFSIZ, 0L);
  723.  
  724.     while (count)
  725.     {
  726.         if (count > ZCOUNT)
  727.             i = ZCOUNT;
  728.         else i = count;
  729.  
  730.     if ((v = wrsects(dev, i, zbuf, start)) != 0)
  731.         break;
  732.     start += i;
  733.     count -= i;
  734.     }
  735.     free(zbuf);
  736.     
  737.     return v;
  738. }
  739.